package kuzha.runtime;

import kuzha.KuzhaObject;
import kuzha.code.CodeBlock;

public class KzUserFunction extends KzFunction {
	public final CodeBlock body;
	public final KuzhaObject parent;
	private final KuzhaObject[] defaultArguments;
	private final String[] argnames;
	
	public KzUserFunction(CodeBlock body, KuzhaObject parent) {
		super();
		this.argnames = new String[0];
		this.body = body;
		this.parent = parent;
		this.defaultArguments = null;
	}
	public KzUserFunction(String[] argnames, KuzhaObject[] defargs, CodeBlock body, KuzhaObject parent) {
		super();
		if (argnames == null || body == null)
			throw new IllegalArgumentException();
		if (defargs != null && argnames.length != defargs.length)
			throw new IllegalArgumentException();
		this.body = body;
		this.parent = parent;
		this.argnames = (String[])argnames.clone();
		this.defaultArguments = defargs != null ? (KuzhaObject[])defargs.clone() : null;
	}
	
	@Override
	public KuzhaObject call(KuzhaObject _this, KuzhaObject... args) {
		KuzhaObject locals = new KzContext(_this, _this, parent);
		if (defaultArguments != null) {
			for(int i = 0; i < argnames.length; i++) {
				if (defaultArguments[i] != null) {
					locals.setSlot(argnames[i], defaultArguments[i]);
				}
			}
		}
		if (args != null) {
			int argc = Math.min(args.length, argnames.length);
			for(int i = 0; i < argc; i++) {
				if (args[i] != null) {
					locals.setSlot(argnames[i], args[i]);
				}
			}
		}
		return body.exec(locals);	
	}
}
